package com.xcity.game.pet;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;

import com.alibaba.fastjson.JSON;
import com.xcity.db.entity.Player;
import com.xcity.game.common.GameStaticConfig;
import com.xcity.game.common.ICalculator;
import com.xcity.game.common.MessageConst;
import com.xcity.game.common.PlayerPool;
import com.xcity.game.event.GameEvents;
import com.xcity.game.mail.MailService;
import com.xcity.game.pet.Pet.State;
import com.xcity.game.skill.SkillTypes;
import com.xcity.pomelo.push.SyncPush;
import com.xcity.pomelo.push.sync.StringSync;

import naga.x.App;
import naga.x.common.Updatable;
import naga.x.game.time.TimeUpdater;

public class PetManager implements Updatable, ICalculator {

	private Player owner;
	private List<Pet> pets;
	private Pet workingPet;
	
	public static final int MAX_CAPACITY = 50;
	protected static final Logger LOG = PetService.LOG;
	
	public PetManager(Player player, List<Pet> pets) {
		owner = player;
		if (pets == null) {
			pets = new ArrayList<Pet>();
		}
		for (int i = 0, size = pets.size(); i < size; i++) {
			Pet pet = pets.get(i);
			pet.vm = this; // ref
			if (pet.getState() == State.WORK) {
				workingPet = pet;
			}
		}
		this.pets = pets;
	}
	
	public List<Pet> getPets() {
		return pets;
	}

	public void setPets(List<Pet> pets) {
		this.pets = pets;
	}
	
	public Pet getPet(long petId) {
		List<Pet> list = pets;
		if (list == null || list.isEmpty()) {
			return null;
		}
		for (int i = list.size() - 1; i >= 0; i--) {
			Pet p = list.get(i);
			if (petId == p.getId()) {
				return p;
			}
		}
		return null;
	}
	
	public boolean addPet(int templateId, String cause) {
		if (pets.size() < MAX_CAPACITY) {
			Pet pet = new Pet(this, templateId); 
			pets.add(pet);
			App.getApp().getEventManager().addEvent(GameEvents.EVENT_ADD_PET, owner, pet);
			LOG.info("[ADDPET]ID[{}]PET[{}]PETTID[{}]CAUSE[{}]", owner.getId(), pet.getId(), pet.getTemplateId(), cause);
			return true;
		}
		return false;
	}
	
	public Pet getWorkingPet() {
		return workingPet;
	}

	public void setWorkingPet(Pet workingPet) {
		Pet old = this.workingPet;
		if (old != null) {
			old.setState(State.FREE);
		}
		this.workingPet = workingPet;
		if (workingPet != null) {
			workingPet.setState(State.WORK);
		}
		owner.send(new StringSync(SyncPush.SYNC_WATCHDOG, workingPet != null ? workingPet.getTemplate().getAnimation() : ""));
	}

	@Override
	public String toString() {
		return JSON.toJSONString(pets);
	}

	@Override
	public boolean update() {
		for (int i = pets.size() - 1; i >= 0; i--) {
			Pet pet = pets.get(i);
			if (!pet.update()) {
				pets.remove(i);
				if (pet == workingPet) {
					setWorkingPet(null);
				}
				if (owner.isOnline()) { // 离线玩家不需要立即删除
					String mailTitle = MessageFormat.format(MessageConst.PET_ESCAPE_MAIL_CONTENT, pet.getTemplate().getName());
					App.getApp().getServiceManager().get(MailService.class).sendSystemMail(owner.getId(), MessageConst.PET_ESCAPE_MAIL_TITLE, mailTitle);
					LOG.info("[PET ESCAPE]ID[{}]PET[{}]", owner.getId(), pet.toString());
				}
			}
		}
		return true;
	}

	public void setOwner(Player player) {
		this.owner = player;
	}

	public Player getOwner() {
		return owner;
	}

	@Override
	public <T> T calc(int id, Object... vals) {
		PetSkill skill;
		update(); // 强制update一下
		if (workingPet == null || (skill = workingPet.getSkillByType(id)) == null) {
			return null;
		}
		switch (id) {
			case SkillTypes.SKILL_REDUCE_BE_ROBBED_LOST:
				return (T) calc0(skill, (int) vals[0]);
			case SkillTypes.SKILL_SHOW_ROBBER_NAME:
				return (T) calc1(skill, (String) vals[0]);
			case SkillTypes.SKILL_INCREASE_FINANCIAL_INTEREST:
				return (T) calc2(skill);
			case SkillTypes.SKILL_REDUCE_SAME_ROBBER_PROBABILITY:
				return (T) calc3(skill, (Player) vals[0]);
			case SkillTypes.SKILL_INCREASE_FRIEND_ROB_RATE:
				return (T) calc4(skill);
			case SkillTypes.SKILL_BIT:
				return (T) calc5(skill, (Player) vals[0]);
		}
		return null;
	}
	
	// 计算减少被掠夺损失比例
	private Integer calc0(PetSkill skill, int buildLevel) {
		if (workingPet.getSpirit() < 70) { // 精神低于70不发动看家护院技能
			return 0;
		}
		int[] params = skill.getLevelUpTemplate().getValue();
		int lvlLimit = params[0];
		if (buildLevel > lvlLimit) {
			return 0;
		}
		int ratio = params[1];
		return ratio;
	}
	
	// 计算被掠夺时是否暴露对方名字(返回 对方名字)
	private String calc1(PetSkill skill, String robberName) {
		int probability = skill.getLevelUpTemplate().getValue()[0] * 100;
		if (Pet.RND.nextInt(GameStaticConfig.defaultChanceBase) < probability) {
			return robberName;
		}
		return null;
	}
	
	// 增加理财收益的比例
	private Integer calc2(PetSkill skill) {
		return skill.getLevelUpTemplate().getValue()[0];
	}
	
	// 计算相同掠夺者这次是否可掠夺成功(返回 是否成功)
	private Boolean calc3(PetSkill skill, Player robber) {
		Set<Long> robPlayerIds = robber.getPool().getObject(PlayerPool.PROPERTY_ROB_PLAYERS, Set.class);
		if (robPlayerIds == null || !robPlayerIds.contains(owner.getId())) {
			// 未被该玩家掠夺过，则必定成功
			return true;
		}
		int probability = skill.getLevelUpTemplate().getValue()[0] * 100;
		if (Pet.RND.nextInt(GameStaticConfig.defaultChanceBase) < probability) {
			return false;
		}
		return true;
	}
	
	// 增加好友掠夺收益比例
	private Integer calc4(PetSkill skill) {
		return skill.getLevelUpTemplate().getValue()[0];
	}
	
	// 计算是否对掠夺者造成无法掠夺状态
	private Boolean calc5(PetSkill skill, Player robber) {
		int probability = skill.getLevelUpTemplate().getValue()[0] * 100;
		if (Pet.RND.nextInt(GameStaticConfig.defaultChanceBase) < probability) {
			robber.poolSet(PlayerPool.PROPERTY_BE_DOG_BIT_TIME, TimeUpdater.getInstance().now());
			return true;
		}
		return false;
	}

}
